using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Xml.Serialization;

namespace SSOConfig
{
    public partial class SSOApplication
    {
        public SSOApplication()
        {
            this.Fields = new Field[] { };
        }

        public SSOApplication(string applicationName, string description, string contactInfo, List<Field> fields)
        {
            this.nameField = applicationName;
            this.descriptionField = description;
            this.contactInfoField = contactInfo;
            this.fieldsField = fields.ToArray();
        }

        public static SSOApplication LoadFromXml(string path)
        {
            if (!File.Exists(path))
            {
                throw new ApplicationException(string.Format("Application config file not found: {0}", path));
            }

            SSOApplication app;
            using (FileStream stream = new FileStream(path, FileMode.Open, FileAccess.Read))
            {
                XmlSerializer serializer = new XmlSerializer(typeof(SSOApplication));
                try
                {
                    app = (SSOApplication)serializer.Deserialize(stream);
                }
                catch (Exception ex)
                {
                    throw new ApplicationException(string.Format("Could not deserialize from XML file: {0}", path), ex);
                }
            }

            return app;
        }

        public static SSOApplication LoadFromSSO(string applicationName)
        {
            SSOApplication app = new SSOHelper().GetApplication(applicationName);
            //if the API has returned the dummy field, remove it:
            List<Field> fields = new List<Field>(app.Fields.Length);
            fields.AddRange(app.Fields);
            int dummyIndex = 0;
            bool dummyReturned = false;
            foreach (Field field in app.Fields)
            {
                if (field.Name == DUMMY_FIELD_NAME)
                {
                    dummyReturned = true;
                    break;
                }
                dummyIndex++;
            }
            if (dummyReturned)
            {
                fields.RemoveAt(dummyIndex);
                app.Fields = fields.ToArray();
            }
            return app;
        }

        public void SaveToXml(string path)
        {
            XmlSerializer serializer = new XmlSerializer(typeof(SSOApplication));
            using (FileStream stream = new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write))
            {

                try
                {
                    serializer.Serialize(stream, this);
                }
                catch (Exception ex)
                {
                    throw new ApplicationException(string.Format("Could not serialize to XML file: {0}", path), ex);
                }
            }
        }

        public void Validate()
        {
            Type fieldType;
            foreach (Field field in this.Fields)
            {
                field.Validate();
            }
        }

        public void SaveToSSO()
        {
            Dictionary<string, Field> fieldDictionary = new Dictionary<string, Field>(this.Fields.Length);
            foreach (Field field in this.Fields)
            {
                fieldDictionary.Add(field.Name, field);
            }
            //we need to inject a dummy field at the start of the list,
            //as SSO always hides the first field when it returns:
            List<Field> fields = new List<Field>(this.Fields.Length);
            if (!fieldDictionary.ContainsKey(DUMMY_FIELD_NAME))
            {
                fields.Add(new Field(DUMMY_FIELD_NAME, false, "System.String", "Dummy value"));
            }
            fields.AddRange(this.Fields);
            this.Fields = fields.ToArray();
            new SSOHelper().CreateApplication(this, true);
        }

        private const string DUMMY_FIELD_NAME = "__dummyField_from_SSOConfigTool";

        public object GetFieldValue(string fieldName)
        {
            object value = null;
            foreach (Field field in this.fieldsField)
            {
                if (field.Name == fieldName)
                {
                    value = field.GetValue();
                    break;
                }
            }
            return value;
        }

    }
}
